package com.link.base.base.esb.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.link.base.base.accnt.model.Account;
import com.link.base.base.accnt.service.AccountService;
import com.link.base.base.contract.model.*;
import com.link.base.base.contract.service.BillInfoService;
import com.link.base.base.contract.service.MaterialCodeService;
import com.link.base.base.contract.service.PriContItemService;
import com.link.base.base.contract.service.ReturnInfoService;
import com.link.base.base.esb.model.EmployeeDTO;
import com.link.base.base.esb.model.EsbInfo;
import com.link.base.base.esb.model.OrgnizationDTO;
import com.link.base.base.esb.model.PositionDTO;
import com.link.base.base.orgnization.model.Orgnization;
import com.link.base.base.orgnization.service.OrgnizationService;
import com.link.base.base.position.model.Position;
import com.link.base.base.position.service.PositionService;
import com.link.base.core.basic.util.ApiUtil;
import com.link.base.core.basic.util.BigDecimalUtils;
import com.link.base.ext.emp.model.EmpPosition;
import com.link.base.ext.emp.model.ExtEmployee;
import com.link.base.ext.emp.service.EmpPositionService;
import com.link.base.ext.emp.service.ExtEmployeeService;
import com.link.core.basic.service.KeyGenerateService;
import com.link.core.cllog.LCLogger;
import com.link.core.util.*;
import com.link.core.util.redisclient.LinkRedisClient;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Objects;


/**
 * 基础数据APIService
 *
 * @author: liuqixin
 * @date: 2020/08/19 15:59
 */
@Service
public class LinkBaseDataApiServiceImpl implements LinkBaseDataApiService {

    private static final Logger logger = LogManager.getLogger(LinkBaseDataApiServiceImpl.class);

    @Resource
    private OrgnizationService orgnizationService;

    @Resource
    private PositionService positionService;

    @Resource
    private ExtEmployeeService extEmployeeService;

    @Resource
    private KeyGenerateService keyGenerateService;

    @Resource
    private EmpPositionService empPositionService;

    @Resource
    private BillInfoService billInfoService;

    @Resource
    private ReturnInfoService returnInfoService;

    @Resource
    private PriContItemService priContItemService;

    @Resource
    private AccountService accountService;

    @Resource
    private MaterialCodeService materialCodeService;

    @Override
    public EsbInfo upsertForESB(EsbInfo esbInfo, OrgnizationDTO orgnizationDto) {
        // 必输或者基础校验
        if (!baseDataCheck(esbInfo, orgnizationDto)) {
            return esbInfo;
        }
        // DTO转Model
        Orgnization orgnization = orgnizationDtoTrans(orgnizationDto);
        // 设置来源
        orgnization.setSource(EsbInfo.SOURCE_ESB);
        Orgnization existOrgnization = null;
        Orgnization existParOrgnization = null;

        try {
            // 查询当前数据库中是否存在此记录
            existOrgnization = orgnizationService.queryUniqueShrOrgnization(orgnization);
            // 查询当前数据库中是否存在父组织记录
            if (StringUtils.isNotBlank(orgnization.getShrParOrgId())) {
                existParOrgnization = orgnizationService.queryUniqueShrParOrgnization(orgnization);
                if (!Objects.isNull(existParOrgnization)) {
                    // 存在父组织时进行父组织ID替换
                    orgnization.setParentOrgId(existParOrgnization.getId());
                }
            }
        } catch (Exception e) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0004)
                    .setAttr1(e.getMessage());
            logger.error("组织基础数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
            return esbInfo;
        }

        // 是否新增标识，默认新增
        boolean insertFlag = true;
        if (Objects.isNull(existOrgnization)) {
            try {
                orgnizationService.insert(orgnization);
            } catch (Exception e) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0005)
                        .setAttr1(e.getMessage());
                logger.error("组织基础数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
                return esbInfo;
            }
        } else {
            insertFlag = false;
            try {
                orgnization.setId(existOrgnization.getId());
                // 设置默认的父组织
                if (Objects.isNull(orgnization.getParentOrgId())) {
                    orgnizationService.setDefaultParOrgnization(orgnization);
                }
                orgnizationService.updateForEsb(orgnization);
            } catch (Exception e) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0006)
                        .setAttr1(e.getMessage());
                logger.error("组织基础数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
                return esbInfo;
            }
        }

        // 根据是否新增或者提示信息，返回成功调用的信息
        if (StringUtils.isNotBlank(orgnizationDto.getShrParOrgId()) && Objects.isNull(existParOrgnization)) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_WARN)
                    .setReturnCodeMsg(EsbInfo.W0001);
        } else {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_SUCCESS)
                    .setReturnCodeMsg(insertFlag ? EsbInfo.A0001 : EsbInfo.A0002);
        }
        return esbInfo;
    }


    @Override
    public EsbInfo upsertForESB(EsbInfo esbInfo, PositionDTO positionDTO) {
        // 必输或者基础校验
        if (!baseDataCheck(esbInfo, positionDTO)) {
            return esbInfo;
        }

        // 基础校验完成后继续转换
        Position position = positionDtoTrans(positionDTO);
        // 设置来源
        position.setSource(EsbInfo.SOURCE_ESB);
        Position existPosition = null;
        Position existParPosition = null;
        // 职位对应组织
        Orgnization posinOrgnization = null;

        // 是否新增标识，默认新增
        boolean insertFlag = true;
        try {
            // 查询当前数据库中是否存在此记录
            existPosition = positionService.queryUniquePosition(position);
            // 判断是否是新建记录
            if (!Objects.isNull(existPosition)) {
                insertFlag = false;
                position.setId(existPosition.getId());
            }
            // 20250604 同鑫HR系统中没用父职位关联，注释掉代码
            /*
            if (!StringUtils.equals(position.getPostnCode(), position.getShrParPostnId())) {
                // 查询当前数据库中是否存在父组织记录
                if (StringUtils.isNotBlank(position.getShrParPostnId())) {
                    existParPosition = positionService.queryUniqueShrParOrgnization(position);
                    // 存在父职位时进行父职位ID替换
                    if (!Objects.isNull(existParPosition)) {
                        position.setParentPositionId(existParPosition.getId());
                    }
                }
            } else {
                // 当父职位跟本职位ID一致时，设置默认组织
                position.setParentPositionId(positionService.queryRoot(position).getId());
            }
            // 查询职位所属组织
            if (StringUtils.isNotBlank(position.getAdminPostnCode())) {
                Orgnization seaOrgnization = new Orgnization();
                seaOrgnization.setOrgCode(position.getAdminPostnCode());
                posinOrgnization = orgnizationService.queryUniqueShrOrgnization(seaOrgnization);
                if (!Objects.isNull(posinOrgnization)) {
                    position.setOrgId(posinOrgnization.getId());
                } else {
                    // 当查询不到时，设置默认组织ID
                    position.setOrgId(orgnizationService.queryRoot(new Orgnization()).getId());
                }
            }
            */
            position.setOrgId(orgnizationService.queryRoot(new Orgnization()).getId());

        } catch (Exception e) {
            logger.error("职位基础数据接口设置默认父职位异常：{}", e.getMessage());
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0004)
                    .setAttr1(e.getMessage());
            logger.error("职位基础数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
            return esbInfo;
        }


        if (insertFlag) {
            try {
                positionService.insert(position);
            } catch (Exception e) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0005)
                        .setAttr1(e.getMessage());
                logger.error("职位基础数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
                return esbInfo;
            }
        } else {
            try {
                positionService.updateForEsb(position);
            } catch (Exception e) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0006)
                        .setAttr1(e.getMessage());
                logger.error("职位基础数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
                return esbInfo;
            }
        }
        // 当关联不到父职位时，返回W提示
        // 20250604 同鑫HR系统中没用父职位关联，去除此判断
//        if (StringUtils.isNotBlank(positionDTO.getShrParPostnId()) && Objects.isNull(position.getParentPositionId())) {
//            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_WARN)
//                    .setReturnCodeMsg(EsbInfo.W0001);
//        } else {
        esbInfo.setReturnStatus(EsbInfo.RT_STATUS_SUCCESS)
                    .setReturnCodeMsg(insertFlag ? EsbInfo.A0001 : EsbInfo.A0002);
//        }
        return esbInfo;
    }

    @Override
    public EsbInfo upsertForESB(EsbInfo esbInfo, BillInfo billInfo) {
        if (!baseDataCheck(esbInfo,billInfo)) {
            return esbInfo;
        }

        boolean insertFlag = false;
        BillInfo exactOne = null;
        try {
            exactOne = billInfoService.queryOneByErpId(billInfo);
        } catch (Exception e) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0999)
                    .setAttr1(e.getMessage());
            logger.error("开票信息数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
            return esbInfo;
        }

        if (exactOne != null) {
            //走更新逻辑
            try {
                billInfo.setId(exactOne.getId());
                billInfoService.update(billInfo);
            } catch (Exception e) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0005)
                        .setAttr1(e.getMessage());
                logger.error("开票信息数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
                return esbInfo;
            }

        } else {
            //走新建逻辑
            insertFlag = true;
            try {
                billInfoService.insert(billInfo);
            } catch (Exception e) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0006)
                        .setAttr1(e.getMessage());
                logger.error("开票信息数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
                return esbInfo;
            }
        }

        esbInfo.setReturnStatus(EsbInfo.RT_STATUS_SUCCESS)
                .setReturnCodeMsg(insertFlag ? EsbInfo.A0001 : EsbInfo.A0002);
        return esbInfo;
    }

    @Override
    public EsbInfo upsertForESB(EsbInfo esbInfo, ReturnInfo returnInfo) {
        if (!baseDataCheck(esbInfo,returnInfo)) {
            return esbInfo;
        }

        boolean insertFlag = false;
        ReturnInfo exactOne = null;
        try {
            exactOne = returnInfoService.queryOneByErpId(returnInfo);
        } catch (Exception e) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0999)
                    .setAttr1(e.getMessage());
            logger.error("回款信息数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
            return esbInfo;
        }

        if (exactOne != null) {
            //走更新逻辑
            try {
                returnInfo.setId(exactOne.getId());
                returnInfoService.update(returnInfo);
            } catch (Exception e) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0005)
                        .setAttr1(e.getMessage());
                logger.error("回款信息数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
                return esbInfo;
            }

        } else {
            //走新建逻辑
            insertFlag = true;
            try {
                returnInfoService.insert(returnInfo);
            } catch (Exception e) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0006)
                        .setAttr1(e.getMessage());
                logger.error("回款信息数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
                return esbInfo;
            }
        }

        esbInfo.setReturnStatus(EsbInfo.RT_STATUS_SUCCESS)
                .setReturnCodeMsg(insertFlag ? EsbInfo.A0001 : EsbInfo.A0002);
        return esbInfo;
    }

    @Override
    public EsbInfo upsertForESB(EsbInfo esbInfo, EmployeeDTO employeeDTO) {
        // 必输或者基础校验
        if (!baseDataCheck(esbInfo, employeeDTO)) {
            return esbInfo;
        }
        // 类转换
        ExtEmployee employee = employeeDtoTrans(employeeDTO);
        // 设置来源
        employee.setSource(EsbInfo.SOURCE_ESB);

        // 查询的数据库对象
        ExtEmployee existEmployee = null;

        // 是否新增标识，默认新增
        boolean insertFlag = true;

        StringBuilder orgPostnWarningMsg = new StringBuilder();
        try {
            // 查询当前数据库中是否存在此记录
            existEmployee = extEmployeeService.queryUniqueByEmpNo(employee);
            if (!Objects.isNull(existEmployee)) {
                insertFlag = false;
                employee.setId(existEmployee.getId());
                employee.setPostnId(existEmployee.getPostnId());
                employee.setUsername(existEmployee.getUsername());
            } else {
                employee.setId(keyGenerateService.keyGenerate());
                if (StringUtils.isBlank(employee.getUsername())) {
                    employee.setUsername(employee.getEmpNo());
                }
            }
        } catch (Exception e) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0004)
                    .setAttr1(e.getMessage());
            logger.error("员工基础数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
            return esbInfo;
        }
        // 赋值员工组织
        Orgnization orgnization = null;
        if (!Objects.isNull(employee) && StringUtils.isNotBlank(employee.getShrDeptId())) {
            orgnization = orgnizationService.queryEmpOrgnizationByEmp(employee);
        }
        if (Objects.isNull(orgnization)) {
            orgPostnWarningMsg.append("无法关联到部门信息;");
        } else {
            // 存在组织时，对组织ID进行替换
            employee.setOrgId(orgnization.getId());
        }

        // 赋值员工职位
        Position position = null;
        if (!Objects.isNull(employee) && StringUtils.isNotBlank(employee.getShrPostnId())) {
            String[] postnCodes = ApiUtil.splitThenWipeOffFirstAndEnd(employee.getShrPostnId(), ",");
            if (postnCodes.length == 0) {
                orgPostnWarningMsg.append("无法拆分出职位编码，请确认职位编码格式;");
            } else {
                position = positionService.queryPositionByPostnCode(postnCodes[0]);
                if (Objects.isNull(position)) {
                    orgPostnWarningMsg.append("无法关联到主职位信息;");
                } else {
                    // 存在职位时，对职位ID进行替换
                    employee.setPostnId(position.getId());
                }
                // 维护职位和员工的中间表，内含事务
                maintainEmpPostns(employee, orgPostnWarningMsg, postnCodes);

            }
        }

        // 能查到存在对象的，进行新增，否则，进行更新
        if (insertFlag) {
            try {
                extEmployeeService.insert(employee);
            } catch (Exception e) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0005)
                        .setAttr1(e.getMessage());
                logger.error("组织基础数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
                return esbInfo;
            }
        } else {
            try {
                extEmployeeService.updateForESB(employee);
            } catch (Exception e) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0006)
                        .setAttr1(e.getMessage());
                logger.error("组织基础数据接口Service异常  -> esbInfo: {}   -> 异常信息：{}", esbInfo, e.getMessage());
                return esbInfo;
            }
        }

        // 根据是否新增或者提示信息，返回成功调用的信息
        if (StringUtils.isNotBlank(orgPostnWarningMsg.toString())) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_WARN)
                    .setReturnCodeMsg(EsbInfo.W0002)
                    .setAttr1(orgPostnWarningMsg.toString());
        } else {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_SUCCESS)
                    .setReturnCodeMsg(insertFlag ? EsbInfo.A0001 : EsbInfo.A0002);
        }
        return esbInfo;
    }

    /**
     * 维护员工的职位中间表
     *
     * @param employee
     * @param postnCodes 职位ID
     */
    @Transactional(rollbackFor = Exception.class)
    void maintainEmpPostns(ExtEmployee employee, StringBuilder warn, String[] postnCodes) {
        if (null == postnCodes || postnCodes.length == 0) {
            return;
        }
        if (StringUtils.isBlank(employee.getId().toString())) {
            warn.append("维护员工职位中间表时，没有赋值员工ID");
            return;
        }
        // 删除员工的员工职位中间表数据
        EmpPosition empPosition = new EmpPosition();
        empPosition.setEmpId(employee.getId());


        // 维护员工职位中间表的数据
        try {
            List<EmpPosition> empPositionList = empPositionService.getInsertEmpPostns(employee, warn, postnCodes);
            empPositionService.deleteAndInsertBatch(empPosition, empPositionList);
        } catch (Exception e) {
            logger.error("员工基础数据接口Service异常  -> 维护员工职位中间表异常 -> 异常信息：{}", e.getMessage());
            warn.append("维护员工职位中间表异常;");
        }

    }


    /**
     * 传输对象转化为基础model
     *
     * @author 刘启鑫
     * @date 2020/8/24 11:42
     */
    private Position positionDtoTrans(PositionDTO positionDTO) {
        Position position = new Position();
        String isEffective = positionDTO.getIsEffective();
        if ("1".equals(isEffective)) {
            isEffective = "Y";
        } else if ("0".equals(isEffective)) {
            isEffective = "N";
        }
        position.setPositionType(positionDTO.getPositionType())
                .setPostnCode(positionDTO.getPostnCode())
                .setAdminPostnCode(positionDTO.getAdminPostnCode())
                .setShrCreated(positionDTO.getShrCreated())
                .setShrPostnId(positionDTO.getShrPostnId())
                .setShrParPostnId(positionDTO.getShrParPostnId())
                .setIsRespPostn(positionDTO.getIsRespPostn())
                .setShrDesc(positionDTO.getShrDesc())
                .setIsEffective(isEffective)
                .setText(positionDTO.getPostnName());
        return position;
    }


    /**
     * 传输对象转化为基础model
     *
     * @author 刘启鑫
     * @date 2020/8/24 11:42
     */
    private Orgnization orgnizationDtoTrans(OrgnizationDTO orgnizationDTO) {
        Orgnization orgnization = new Orgnization();
        orgnization.setText(orgnizationDTO.getText());
        orgnization.setOrgCode(orgnizationDTO.getOrgCode());
        orgnization.setShrParOrgId(orgnizationDTO.getShrParOrgId());
        if ("1".equals(orgnizationDTO.getIsEffective())) {
            orgnization.setIsEffective("Y");
        } else if ("0".equals(orgnizationDTO.getIsEffective())) {
            orgnization.setIsEffective("N");
        } else {
            orgnization.setIsEffective(orgnizationDTO.getIsEffective());
        }
        orgnization.setShrOrgId(orgnizationDTO.getShrOrgId());
        orgnization.setOrgType(orgnizationDTO.getOrgType());
        orgnization.setOrgLevel(orgnizationDTO.getOrgLevel());
        orgnization.setShrDesc(orgnizationDTO.getShrDesc());
        orgnization.setShrCreated(orgnizationDTO.getShrCreated());
        return orgnization;
    }

    /**
     * 传输对象转化为基础model
     *
     * @author 刘启鑫
     * @date 2020/8/24 11:42
     */
    private ExtEmployee employeeDtoTrans(EmployeeDTO employeeDTO) {
        ExtEmployee employee = new ExtEmployee();
        employee.setEmpType("VendorEmployee");
        employee.setFstName(employeeDTO.getFstName());
        employee.setEmpNo(employeeDTO.getEmpNo());
        employee.setEmpIdNo(employeeDTO.getEmpIdNo());
        employee.setEmpStatus("NORMAL");
        employee.setShrDeptId(employeeDTO.getShrDeptId());
        employee.setShrPostnId(employeeDTO.getShrPostnId());
        employee.setShrCreated(employeeDTO.getShrCreated());
        if ("男".equals(employeeDTO.getGender())) {
            employee.setGender("MALE");
        } else {
            employee.setGender("FEMALE");
        }
        employee.setEmpTel(employeeDTO.getEmpTel());
        employee.setEmpOfficeTel(employeeDTO.getEmpOfficeTel());
        employee.setEmpMail(employeeDTO.getEmpMail());
        employee.setEmpWhchatNo(employeeDTO.getEmpWhchatNo());
        employee.setShrEmpId(employeeDTO.getShrEmpId());
        employee.setUsername(employeeDTO.getUsername());
        employee.setShrDesc(employeeDTO.getShrDesc());
        return employee;
    }

    /**
     * EsbInfo基础校验
     *
     * @param esbInfo
     * @return
     */
    private Boolean esbInfoCheck(EsbInfo esbInfo) {
        // EsbInfo 非空校验
        if (Objects.isNull(esbInfo)) {
            esbInfo = new EsbInfo();
            esbInfo.setInstId(keyGenerateService.keyGenerate().toString())
                    .setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0001);
            return false;
        }
        // 请求时间校验
        if (StringUtils.isBlank(esbInfo.getRequestTime())) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0007)
                    .setAttr1("EsbInfo的请求时间(requestTime)字段为空");
            return false;
        }
        return true;
    }


    /**
     * 职位基础数据校验
     *
     * @param esbInfo
     * @param positionDTO
     * @return
     */
    private Boolean baseDataCheck(EsbInfo esbInfo, PositionDTO positionDTO) {
        // EsbInfo 校验
        if (!esbInfoCheck(esbInfo)) {
            return false;
        }
        // 数据非空校验
        if (Objects.isNull(positionDTO)) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0002);
            return false;
        }
        // Shr创建时间校验
        if (StringUtils.isNotBlank(positionDTO.getShrCreated())) {
            if (!ApiUtil.isValidDate(ApiUtil.TIME_FORMAT, positionDTO.getShrCreated())) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0003)
                        .setAttr1("requestInfo的源系统创建时间(shrCreated)字段格式错误");
                return false;
            }
        } else {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0007)
                    .setAttr1("requestInfo的源系统创建时间(shrCreated)字段为空");
            return false;
        }
        // 源系统职位ID非空校验
        /*
        if (StringUtils.isBlank(positionDTO.getShrPostnId())) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0007)
                    .setAttr1("requestInfo的职位ID(shrPostnId)字段为空");
            return false;
        }
         */
        if (StringUtils.isBlank(positionDTO.getPostnCode())) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0007)
                    .setAttr1("requestInfo的职位编码(postnCode)字段为空");
            return false;
        }
        return true;
    }


    /**
     * 组织基础数据校验
     *
     * @param esbInfo
     * @param orgnizationDTO
     * @return
     */
    private Boolean baseDataCheck(EsbInfo esbInfo, OrgnizationDTO orgnizationDTO) {
        // EsbInfo 校验
        if (!esbInfoCheck(esbInfo)) {
            return false;
        }
        // 数据非空校验
        if (Objects.isNull(orgnizationDTO)) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0002);
            return false;
        }
        // Shr创建时间校验
        if (StringUtils.isNotBlank(orgnizationDTO.getShrCreated())) {
            if (!ApiUtil.isValidDate(ApiUtil.TIME_FORMAT, orgnizationDTO.getShrCreated())) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0003)
                        .setAttr1("requestInfo的源系统创建时间(shrCreated)字段格式错误");
                return false;
            }
        } else {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0007)
                    .setAttr1("requestInfo的源系统创建时间(shrCreated)字段为空");
            return false;
        }
        // 源系统组织ID非空校验
        /*
        if (StringUtils.isBlank(orgnizationDTO.getShrOrgId())) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0007)
                    .setAttr1("requestInfo的SHR组织ID(shrOrgId)字段为空");
            return false;
        }
        */
        // 组织编码非空校验
        if (StringUtils.isBlank(orgnizationDTO.getOrgCode().trim())) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0007)
                    .setAttr1("requestInfo的组织编码(orgCode)字段为空");
            return false;
        }
        return true;
    }

    /**
     * 员工基础数据校验
     *
     * @param esbInfo
     * @param employeeDTO
     * @return
     */
    private Boolean baseDataCheck(EsbInfo esbInfo, EmployeeDTO employeeDTO) {
        // EsbInfo 校验
        if (!esbInfoCheck(esbInfo)) {
            return false;
        }
        if (Objects.isNull(employeeDTO)) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0002);
            return false;
        }
        if (StringUtils.isNotBlank(employeeDTO.getShrCreated())) {
            if (!ApiUtil.isValidDate(ApiUtil.TIME_FORMAT, employeeDTO.getShrCreated())) {
                esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                        .setReturnCodeMsg(EsbInfo.E0003)
                        .setAttr1("requestInfo的源系统创建时间(shrCreated)字段格式错误");
                return false;
            }
        } else {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0007)
                    .setAttr1("requestInfo的源系统创建时间(shrCreated)字段为空");
            return false;
        }
        if (StringUtils.isBlank(employeeDTO.getShrEmpId())) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0007)
                    .setAttr1("requestInfo的SHR员工ID(shrEmpId)字段为空");
            return false;
        }
        if (StringUtils.isBlank(employeeDTO.getEmpNo().trim())) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0007)
                    .setAttr1("requestInfo的员工编码(empNo)字段为空");
            return false;
        }
        return true;
    }

    private boolean baseDataCheck(EsbInfo esbInfo, BillInfo billInfo) {
        if (!esbInfoCheck(esbInfo)) {
            return false;
        }
        if (Objects.isNull(billInfo)) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0002);
            return false;
        }
        //判断erpId是否为空
        if (StringUtils.isBlank(billInfo.getErpId())) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0007)
                    .setAttr1("requestInfo的源系统ERP开票系统ID字段为空");
            return false;
        }
        return true;
    }

    private boolean baseDataCheck(EsbInfo esbInfo, ReturnInfo returnInfo) {
        if (!esbInfoCheck(esbInfo)) {
            return false;
        }
        if (Objects.isNull(returnInfo)) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0002);
            return false;
        }
        //判断erpId是否为空
        if (StringUtils.isBlank(returnInfo.getErpId())) {
            esbInfo.setReturnStatus(EsbInfo.RT_STATUS_ERROR)
                    .setReturnCodeMsg(EsbInfo.E0007)
                    .setAttr1("requestInfo的源系统ERP回款系统ID字段为空");
            return false;
        }
        return true;
    }

    @Test
    public void test() throws Exception {
        //Map<String, Object> resultMap = new HashMap<>();  //最终返回的结果
        String requestUrl = "http://192.168.0.233:8082/v1/kingdeecloud/receivableBillInvoice/query";
        //PropertyUtil.getCommonProperty("invoiceUrl"); //获取公共参数（里面放参数key）
        //PropertyUtil.getProperty("invoiceUrl",0L);
        // 转换成特定格式字符串 打开url的http请求
        URL url = new URL(requestUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
        // 提交模式
        httpURLConnection.setRequestMethod("POST");  //接口文档上标注的传输方式
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setDoInput(true);
        httpURLConnection.setRequestProperty("Authorization","Basic Y3JtMDE6ZGV2QGNybSM"); //这里改为参数配置的key
        httpURLConnection.setRequestProperty("Content-type", "application/json");

        //构造参数  就是构造请求body
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("FormId","AR_receivable");
             //里面放着所有的列属性
        jsonObject.put("FieldKeys","FID,FMaterialId.F_YBKJ_ASSISTANT,FMaterialId.FSpecification,FBillNo,FALLAMOUNTFOR_D ,FDATE,"
                + "FCreatorId.FName,FSETTLEORGID.FNAME,FCURRENCYID.FName,FWRITTENOFFSTATUS,FCUSTOMERID.FName");
        jsonObject.put("FilterString","");
        jsonObject.put("TopRowCount",0);
        jsonObject.put("StartRow",0);
        jsonObject.put("Limit",10);

        //new一个json 放入刚才构造的请求body
        JSONArray jsonArray = new JSONArray();
        jsonArray.add(jsonObject);
        //new一个json对象 把刚才的json数组外面再加一层
        JSONObject paramJson = new JSONObject();
        paramJson.put("parameters",jsonArray);
        //至此，请求body成形，将他转化为字符串格式
        String data = JsonUtil.toString(paramJson);
        logger.info(data);
        PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
        //发送参数 把刚才的请求body写入http请求流
        printWriter.write(data);
        printWriter.flush();
        String line;
        String result = "";
        //获取返回内容  读取返回结果
        BufferedReader in = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
        while ((line = in.readLine()) != null) {
            result += line;
        }
        //处理返回数据Str---result
        logger.info(result);

    }

    @Override
    public void upsertInvoiceInfoFromERP() throws Exception {
        //查询应收单开票信息
        JSONArray resultLists = queryInvoiceInfo();
        //处理返回数据,遍历更新数据

//        JSONArray a = new JSONArray(resultStr);
        int resultListsSize = resultLists.size();
        int l;   //外层 循环变量
        int i;  //内层 循环变量
        for (l = 0 ; l < resultListsSize; l++) {
//            String resultArrayStr = (String) resultLists.get(l);
            JSONArray resultArray = JSONArray.parseArray((String) resultLists.get(l));
//            JSONArray resultArray = (JSONArray) resultLists.get(l);
            BillInfo billInfo = new BillInfo();

            int arraySize = resultArray.size();
            for ( i = 0 ; i < arraySize ;i++) {
                JSONArray invoiceInfo = JSON.parseArray(resultArray.get(i).toString());
                billInfo.setErpId(String.valueOf(invoiceInfo.get(0)));  //erp开票单ID
                billInfo.setProdCode(String.valueOf(invoiceInfo.get(1))); //零件号
                billInfo.setBillInfoCode(String.valueOf(invoiceInfo.get(2)));//开票单编号
                billInfo.setDrawAmount(String.valueOf(invoiceInfo.get(3)));//开票金额
                billInfo.setActDrawDate(String.valueOf(invoiceInfo.get(4)));//开票时间
                billInfo.setDrawerId(String.valueOf(invoiceInfo.get(5)));//开票人
                billInfo.setInvoiceTitle(String.valueOf(invoiceInfo.get(6)));//开票单位
                billInfo.setCurrency(String.valueOf(invoiceInfo.get(7)));//币种
                billInfo.setInfoStatus(String.valueOf(invoiceInfo.get(8)));//核销状态
                billInfo.setAcctName(String.valueOf(invoiceInfo.get(9)));//客户名称
                billInfo.setProdName(String.valueOf(invoiceInfo.get(10)));//零件名称
                billInfo.setErpRowId(String.valueOf(invoiceInfo.get(11)));//erp开票行ID
                billInfo.setAcctCode(String.valueOf(invoiceInfo.get(12)));//客户编码
                billInfo.setPartNum(String.valueOf(invoiceInfo.get(13)));//零件数量
                billInfo.setPartPrice(String.valueOf(invoiceInfo.get(14)));//零件单价
                logger.info("开票信息数据接口 -> JobHandler:invoiceJobHandler -> 接收数据：{}", billInfo.toString());
                //数据校验
                billInfoCheck(billInfo);
                BillInfo exactOne = billInfoService.queryOneByErpId(billInfo);
                if (exactOne != null) {
                    //走更新逻辑
                    try {
                        billInfo.setId(exactOne.getId());
                        billInfoService.update(billInfo);
                    } catch (Exception e) {
                        logger.error("开票信息数据接口Service异常 -> 异常数据: {} -> 异常信息：{}", billInfo,e.getMessage());
                    }
                } else {
                    //走新建逻辑
                    try {
                        billInfo.setId(keyGenerateService.keyGenerate());
                        billInfoService.insert(billInfo);
                    } catch (Exception e) {
                        logger.error("开票信息数据接口Service异常 -> 异常数据: {} -> 异常信息：{}", billInfo ,e.getMessage());
                    }
                }
            }
        }

    }

    /**
     * 查询应收单开票信息
     * @return
     * @throws Exception
     */
    public JSONArray queryInvoiceInfo() throws Exception {
        //获取公共参数 查询应收单开票信息
        String requestUrl  = PropertyUtil.getCommonProperty("invoiceUrl");
        // 转换成特定格式字符串 打开url的http请求
        URL url = new URL(requestUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
        // 提交模式
        httpURLConnection.setRequestMethod("POST");  //接口文档上标注的传输方式
        httpURLConnection.setDoOutput(true);// URL连接可用于输入和/或输出。如果您打算将URL连接用于输出，请将DoOutput标志设置为true，否则将其设置为false
        httpURLConnection.setDoInput(true);
        httpURLConnection.setRequestProperty("Authorization",PropertyUtil.getCommonProperty("invoiceUrlAuth")); //设置常规请求属性 这里改为参数配置的key
        httpURLConnection.setRequestProperty("Content-type", "application/json");

        //构造参数  就是构造请求body-->{body}
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("FormId","AR_receivable");
        //里面放着所有的列属性
        jsonObject.put("FieldKeys","FID,FMaterialId.FSpecification,FBillNo,FALLAMOUNTFOR_D ,FDATE,"
                + "FCreatorId.FName,FSETTLEORGID.FNAME,FCURRENCYID.FName,FWRITTENOFFSTATUS,"
                + "FCUSTOMERID.FName,FMaterialId.Fname,FEntityDetail_FEntryID,FCUSTOMERID.Fnumber,FPriceQty,FPrice");
        jsonObject.put("FilterString","datediff(week,FAPPROVEDATE ,getdate()) = 1 and FDOCUMENTSTATUS = 'C'");    //查询最后更新时间在前1周的数据
        jsonObject.put("OrderString","FApproveDate asc");
        jsonObject.put("TopRowCount",0);
        jsonObject.put("StartRow",0);
        jsonObject.put("Limit",1000);

        //new一个json数组 刚才构造的请求{body}对象外加一层 -->[{body}]
        JSONArray jsonArray = new JSONArray();
        jsonArray.add(jsonObject);
        //new一个json对象 把刚才的[{body}]外面再加一层 --> {"parameters":[{body}]}
        JSONObject paramJson = new JSONObject();
        paramJson.put("parameters",jsonArray);
        //至此，请求body成形，将他转化为字符串格式
        String data = JsonUtil.toString(paramJson);
        logger.info(data);

        //返回写入此连接的输出流。
        PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
        //发送参数 把刚才的请求body写入http输出流
        printWriter.write(data);
        printWriter.flush();
        String line;
        JSONArray resultList = new JSONArray();
        for (int i = 0 ; i < 5 ;i++) {
            String result = "";
            //返回这个打开的链接读取的输入流 获取返回内容  逐行读取返回结果
            BufferedReader in = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
            while ((line = in.readLine()) != null) {
                result += line;
            }
            logger.info(result);
            if (result == null || result == "") {
                //为空说明上周更新的数据全部查完 跳出本循环 返回数组
                break;
            } else {
                //不为空，则说明查询到数据，addlist
                resultList.add(result);
                //动态构造StartRow
                LinkRedisClient jedis = RedisUtil.getJedis();
                int startRow = 0 ;
                try {
                    String redisKey = "interfaceStartRow" + "/" + DateUtil.dateToStr(new Date(), "yyyyMMdd");

                    if (jedis.hexists(redisKey,"invoiceInfo")) {
                        //有今天的key,说明不是第一次查询-->在原有的值得基础上+1000
                        int old = Integer.parseInt(jedis.hget(redisKey, "invoiceInfo"));
                        jedis.hincrBy(redisKey,"invoiceInfo",1000);
                        startRow = Integer.parseInt(jedis.hget(redisKey, "invoiceInfo"));
                    } else {
                        //没有今天的key,说明第2次查询[startRow赋值1000]-->创建以上述RedisKey为key,值为1000的数据
                        jedis.hset(redisKey,"invoiceInfo", String.valueOf(1000));
                        startRow = Integer.parseInt(jedis.hget(redisKey, "invoiceInfo"));
                    }
                } catch (Exception e) {
                    LCLogger.withException(e);
                } finally {
                    RedisUtil.returnResource(jedis);
                }
                jsonObject.put("StartRow",startRow);
            }
        }
        return resultList;
    }

    /**
     * 开票信息校验
     * @param billInfo
     */
    private void billInfoCheck(BillInfo billInfo) {
        if (Objects.isNull(billInfo)) {
            logger.error("开票信息数据接口Service异常  -> 异常信息：{}", "保存数据对象为空");
        }
        //判断erpId  erp开票信息行是否为空
        if (StringUtils.isBlank(billInfo.getErpId()) || StringUtils.isBlank(billInfo.getErpRowId())) {
            logger.error("开票信息数据接口Service异常  -> 异常信息：{}", "字段非空校验失败");
        }
    }

    /**
     * 查询收款单回款信息并更新
     * @return
     * @throws Exception
     */
    @Override
    public void upsertReturnInfoFromERP() throws Exception {
        //查询收款单回款信息
        JSONArray resultLists = queryReturnInfo();
        //处理返回数据
//        JSONArray resultArray = (JSONArray) JSON.parse(resultStr);
        int resultListsSize = resultLists.size();
        int l;   //外层 循环变量
        int i;  //内层 循环变量
        for (l = 0 ; l < resultListsSize; l++) {
            JSONArray resultArray = JSONArray.parseArray((String) resultLists.get(l));
//            JSONArray resultArray = JSONArray.parseArray(resultStr);
            int arraySize = resultArray.size();
            ReturnInfo returnInfo = new ReturnInfo();
            for (i = 0 ; i < arraySize ; i++) {
//            JSONArray returnData = JSON.parseArray(resultArray.get(i).toString());
                JSONArray returnData  = resultArray.getJSONArray(i);
                returnInfo.setErpId(String.valueOf(returnData.get(0)));//ERP回款单ID
                returnInfo.setInfoCode(String.valueOf(returnData.get(1)));//回款单号
                returnInfo.setReturnTime(String.valueOf(returnData.get(2)));//回款日期
                returnInfo.setReturnType(String.valueOf(returnData.get(3)));//往来单位类型
                returnInfo.setAcctId(String.valueOf(returnData.get(4)));//往来单位
                returnInfo.setCurrencyType(String.valueOf(returnData.get(5)));//币别
                returnInfo.setMustReceive(String.valueOf(returnData.get(6)));//应收金额
                returnInfo.setReturnAmount(String.valueOf(returnData.get(7)));//实收金额
                returnInfo.setFinancialConfirmer(String.valueOf(returnData.get(8)));//收款组织
                returnInfo.setConfirmTime(String.valueOf(returnData.get(9)));//结算组织
                logger.info("回款信息数据接口 -> JobHandler:upsertReturnInfoJobHandler -> 接收数据：{}", returnInfo.toString());
                //数据校验
                returnInfoCheck(returnInfo);
                ReturnInfo exactOne = returnInfoService.queryOneByErpId(returnInfo);
                if (exactOne != null) {
                    //走更新逻辑
                    try {
                        returnInfo.setId(exactOne.getId());
                        returnInfoService.update(returnInfo);
                    } catch (Exception e) {
                        logger.error("回款信息数据接口Service异常 -> 异常数据: {} -> 异常信息：{}", returnInfo , e.getMessage());
                    }
                } else {
                    //走新建逻辑
                    try {
                        returnInfo.setId(keyGenerateService.keyGenerate());
                        returnInfoService.insert(returnInfo);
                    } catch (Exception e) {
                        logger.error("回款信息数据接口Service异常 -> 异常数据: {} -> 异常信息：{}", returnInfo , e.getMessage());
                    }
                }
            }
        }
    }

    /**
     * 查询收款单回款信息
     * @return
     * @throws Exception
     */
    public JSONArray queryReturnInfo() throws Exception {
        //获取公共参数 查询应收单开票信息
        String requestUrl  = PropertyUtil.getCommonProperty("returnInfoUrl");
        // 转换成特定格式字符串 打开url的http请求
        URL url = new URL(requestUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
        // 提交模式
        httpURLConnection.setRequestMethod("POST");  //接口文档上标注的传输方式
        httpURLConnection.setDoOutput(true);// URL连接可用于输入和/或输出。如果您打算将URL连接用于输出，请将DoOutput标志设置为true，否则将其设置为false
        httpURLConnection.setDoInput(true);
        httpURLConnection.setRequestProperty("Authorization",PropertyUtil.getCommonProperty("returnUrlAuth")); //设置常规请求属性 这里改为参数配置的key
        httpURLConnection.setRequestProperty("Content-type", "application/json");

        //构造参数  就是构造请求body-->{body}
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("FormId","AR_RECEIVEBILL");
        //里面放着所有的列属性
        jsonObject.put("FieldKeys","FID,FBillNo,FDATE,FCONTACTUNITTYPE,FCONTACTUNIT.FName,FCURRENCYID.FName,"
                + "FRECEIVEAMOUNTFOR_H,FREALRECAMOUNTFOR,FPAYORGID.FName,FSETTLEORGID.FName");
        jsonObject.put("FilterString","datediff(week,FAPPROVEDATE,getdate()) = 1 and FDOCUMENTSTATUS = 'C'");  //最后更新时间在上周的数据
        jsonObject.put("OrderString","FApproveDate asc");
        jsonObject.put("TopRowCount",0);
        jsonObject.put("StartRow",0);
        jsonObject.put("Limit",1000);

        //new一个json数组 刚才构造的请求{body}对象外加一层 -->[{body}]
        JSONArray jsonArray = new JSONArray();
        jsonArray.add(jsonObject);
        //new一个json对象 把刚才的[{body}]外面再加一层 --> {"parameters":[{body}]}
        JSONObject paramJson = new JSONObject();
        paramJson.put("parameters",jsonArray);
        //至此，请求body成形，将他转化为字符串格式
        String data = JsonUtil.toString(paramJson);
        logger.info(data);

        //返回写入此连接的输出流。
        PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
        //发送参数 把刚才的请求body写入http输出流
        printWriter.write(data);
        printWriter.flush();
        String line;
        JSONArray resultList = new JSONArray();
        for (int i = 0 ; i < 5 ;i++) {
            String result = "";
            //返回这个打开的链接读取的输入流 获取返回内容  逐行读取返回结果
            BufferedReader in = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
            while ((line = in.readLine()) != null) {
                result += line;
            }
            logger.info(result);
            if (result == null || result == "") {
                //为空说明上周更新的数据全部查完 跳出本循环 返回数组
                break;
            } else {
                //不为空，则说明查询到数据，addlist
                resultList.add(result);
                //动态构造StartRow
                LinkRedisClient jedis = RedisUtil.getJedis();
                int startRow = 0 ;
                try {
                    String redisKey = "interfaceStartRow" + "/" + DateUtil.dateToStr(new Date(), "yyyyMMdd");

                    if (jedis.hexists(redisKey,"returnInfo")) {
                        //有今天的key,说明不是第一次查询-->在原有的值得基础上+1000
//                        int old = Integer.parseInt(jedis.hget(redisKey, "returnInfo"));
                        jedis.hincrBy(redisKey,"returnInfo",1000);
                        startRow = Integer.parseInt(jedis.hget(redisKey, "returnInfo"));
                    } else {
                        //没有今天的key,说明第2次查询[startRow赋值1000]-->创建以上述RedisKey为key,值为1000的数据
                        jedis.hset(redisKey,"returnInfo", String.valueOf(1000));
                        startRow = Integer.parseInt(jedis.hget(redisKey, "returnInfo"));
                    }
                } catch (Exception e) {
                    LCLogger.withException(e);
                } finally {
                    RedisUtil.returnResource(jedis);
                }
                jsonObject.put("StartRow",startRow);
            }
        }
        return resultList;
    }

    /**
     * 回款信息校验
     * @param returnInfo
     */
    private void returnInfoCheck(ReturnInfo returnInfo) {
        if (Objects.isNull(returnInfo)) {
            logger.error("回款信息数据接口Service异常  -> 异常信息：{}", "保存数据对象为空");
        }
        //判断erpId  erp开票信息行是否为空
        if (StringUtils.isBlank(returnInfo.getErpId())) {
            logger.error("回款信息数据接口Service异常  -> 异常信息：{}", "字段非空校验失败");
        }
    }

    /**
     * 根据传进来的价格合同，查询产品行list,同步产品行及头信息至ERP
     * @param entity
     * @throws Exception
     */
    @Override
    public void syncPriContract(ModContract entity) throws Exception {
        //根据价格合同ID查询产品行
        PriContItem querItem = new PriContItem();
        querItem.setContractId(entity.getId());
        List<PriContItem> priContItems = priContItemService.queryAll(querItem);
        //头行全部传参
        EsbInfo esbInfo = syncContractToERP(entity,priContItems);

        logger.info("价格合同同步接口 -> URL:/link/modContract -> 返回信息：{}", esbInfo);
    }

    /**
     * 调用ERP价格合同写入接口
     * @return
     * @throws Exception
     */
    public EsbInfo syncContractToERP(ModContract modContract,List<PriContItem> priContItems) throws Exception {
        //获取公共参数 查询应收单开票信息
        String requestUrl  = PropertyUtil.getCommonProperty("syncPriContractUrl");
        // 转换成特定格式字符串 打开url的http请求
        URL url = new URL(requestUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
        // 提交模式
        httpURLConnection.setRequestMethod("POST");  //接口文档上标注的传输方式
        httpURLConnection.setDoOutput(true);// URL连接可用于输入和/或输出。如果您打算将URL连接用于输出，请将DoOutput标志设置为true，否则将其设置为false
        httpURLConnection.setDoInput(true);
        httpURLConnection.setRequestProperty("Authorization",PropertyUtil.getCommonProperty("returnUrlAuth")); //设置常规请求属性 这里改为参数配置的key
        httpURLConnection.setRequestProperty("Content-type", "application/json");

        //构造参数 由内到外，从最内层零件对象开始
        JSONArray fEntityArray = new JSONArray(); //存放零件对象的数组
        //遍历零件信息，构造零件实体--> {body}
        for (PriContItem priContItem : priContItems) {
            JSONObject partObject = new JSONObject(true);  //零件对象
            JSONObject fMaterialId = new JSONObject();   //物料编码
            JSONObject fUnitID = new JSONObject();   //计价单位对象
            JSONObject fYbkjAssistant = new JSONObject();//价格类别

            String MaterialCode = StringUtils.null2EmptyString(priContItem.getMaterialCode());
            String fBaseUnitCode = StringUtils.replaceNullString(priContItem.getfBaseUnitCode());
            BigDecimal noTaxPrice = BigDecimalUtils.changeNullToZero(priContItem.getNoTaxPrice());

            fMaterialId.put("FNumber",MaterialCode);//物料编码
            fUnitID.put("FNumber",fBaseUnitCode);  //计价单位：直接传过来单位编码
            fYbkjAssistant.put("FNumber","002"); //价格类别：默认002
            partObject.put("FMaterialId",fMaterialId);//物料编码
            partObject.put("FUnitID",fUnitID);//计价单位
            partObject.put("FPriceBase",1.0); //价格系数：默认1
            partObject.put("FPrice",noTaxPrice); //未税单价
            partObject.put("FDownPrice",noTaxPrice);//最低限价 = 未税单价
            partObject.put("F_ybkj_Assistant1",fYbkjAssistant); //价格类别
            fEntityArray.add(partObject);
        }

        JSONArray fEntityArray2 = new JSONArray(); //存放适用客户的数组
        JSONObject custObject = new JSONObject(); //存放客户信息的对象
        JSONObject fCustID = new JSONObject();

        fCustID.put("FNumber","006");//客户编号默认：006
        custObject.put("FCustID",fCustID);
        custObject.put("FIsDefList",false); //默认价目表
        fEntityArray2.add(custObject);

        JSONObject model = new JSONObject(true);    //存放头行信息
        JSONObject fCreateOrgId = new JSONObject();  //创建组织
        JSONObject fCurrencyId = new JSONObject();  //币别

        String billType = StringUtils.replaceNullString(modContract.getBillType());
        String contractName = StringUtils.replaceNullString(modContract.getContractName());
        String beginDate = StringUtils.replaceNullString(modContract.getBeginDate());
        String endDate = StringUtils.replaceNullString(modContract.getEndDate());
        fCreateOrgId.put("FNumber","00");//创建组织：默认00
        fCurrencyId.put("FNumber",billType);//币别

        model.put("FName",contractName); //合同名称
        model.put("FCreateOrgId",fCreateOrgId);//创建组织
        model.put("FCurrencyId",fCurrencyId); //币别
        model.put("FPriceObject","A"); //价目对象：默认A
        model.put("FEffectiveDate",beginDate);//合同有效期起
        model.put("FExpiryDate",endDate);//合同有效期止
        model.put("FIsIncludedTax",false); //含税：false
        model.put("FLimitCustomer","1"); //限定客户：默认1
        model.put("FEntity",fEntityArray);//零件信息数组
        model.put("FEntity2",fEntityArray2);//客户信息数组

        JSONArray needUpDateFields = new JSONArray();
        JSONArray needReturnFields = new JSONArray();

        JSONObject jsonObject = new JSONObject(true);
        jsonObject.put("Creator","");
        jsonObject.put("NeedUpDateFields",needUpDateFields);
        jsonObject.put("NeedReturnFields",needReturnFields);
        jsonObject.put("IsDeleteEntry","true");
        jsonObject.put("SubSystemId","");
        jsonObject.put("IsVerifyBaseDataField","false");
        jsonObject.put("IsEntryBatchFill","true");
        jsonObject.put("ValidateFlag","true");
        jsonObject.put("NumberSearch","true");
        jsonObject.put("InterationFlags","");
        jsonObject.put("IsAutoSubmitAndAudit","true");   // //传输至ERP是审核通过状态,新增是true，更新是false
        jsonObject.put("Model",model);

        JSONArray requestArray = new JSONArray();
        requestArray.add("BD_SAL_PriceList");
        requestArray.add(jsonObject);

        JSONObject requestObject = new JSONObject();
        requestObject.put("parameters",requestArray);
        //至此，请求body成形，将他转化为字符串格式
        String data = JsonUtil.toString(requestObject);
        logger.info(data);

        //返回写入此连接的输出流。
        PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
        //发送参数 把刚才的请求body写入http输出流
        printWriter.write(data);
        printWriter.flush();
        String line;
        String result = "";
        //返回这个打开的链接读取的输入流 获取返回内容  逐行读取返回结果
        BufferedReader in = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
        while ((line = in.readLine()) != null) {
            result += line;
        }
        logger.info(result);
        //response信息处理
        EsbInfo esbInfo = analyzeResponse(result);
        return esbInfo;
    }

    /**
     * 将传入的客户头信息，同步至ERP
     * @param entity
     * @return
     * @throws Exception
     */
    @Override
    public void syncAccountInfo(Account entity) throws Exception {
        //根据传进来的客户ID，查询客户信息
        Account account = accountService.queryById(entity);
        if (account == null) {
            //没找到对应合同头：未找到对应的合同头信息，请检查
            logger.info("客户新建信息同步接口 -> URL:/link/accnt -> 异常信息：{}  -> 客户ID：{}", "未找到对应的客户头信息，客户信息同步失败",entity.getId());
        }
        //调用ERP客户写入接口
        EsbInfo esbInfo = syncAccountToERP(account);
        logger.info("客户新建信息同步接口 -> URL:/link/accnt -> 返回信息：{}", esbInfo);
        //20210729 获取返回的erpID存值
        account.setErpId(esbInfo.getAttr1());
        accountService.update(account);
    }

    /**
     * 客户新建生效
     * 调用ERP客户写入接口，新建插入erp数据
     * @return
     * @throws Exception
     */
    public EsbInfo syncAccountToERP(Account account) throws Exception {
        //获取公共参数 查询应收单开票信息
        String requestUrl  = PropertyUtil.getCommonProperty("syncAccountInfo");
        // 转换成特定格式字符串 打开url的http请求
        URL url = new URL(requestUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
        // 提交模式
        httpURLConnection.setRequestMethod("POST");  //接口文档上标注的传输方式
        httpURLConnection.setDoOutput(true);// URL连接可用于输入和/或输出。如果您打算将URL连接用于输出，请将DoOutput标志设置为true，否则将其设置为false
        httpURLConnection.setDoInput(true);
        httpURLConnection.setRequestProperty("Authorization",PropertyUtil.getCommonProperty("returnUrlAuth")); //设置常规请求属性 这里改为参数配置的key
        httpURLConnection.setRequestProperty("Content-type", "application/json");

        //构造参数 由内到外，从最内层零件对象开始
        JSONObject model = new JSONObject(true);    //存放头信息,有序
        JSONObject fCreateOrgId = new JSONObject();  //创建组织
        JSONObject fUseOrgId = new JSONObject();  //使用组织
        JSONObject fCOUNTRY = new JSONObject();//国家
        JSONObject fCustTypeId = new JSONObject();//客户类别
        JSONObject fCurrencyId = new JSONObject();  //币别
        JSONObject fTaxType = new JSONObject();//税分类
        JSONObject fTaxRate = new JSONObject();//默认税率
        JSONObject ftBdCustomerext = new JSONObject();//商务信息

        String country = StringUtils.replaceNullString(account.getCountry());
        String acctCategor = StringUtils.replaceNullString(account.getAcctCategory());
        //币别转换
        String currency = StringUtils.replaceNullString(account.getCurrency());
        switch (currency) {
            case "CNY":
                currency = "PRE001";  //人民币
                break;
            case "HKD":
                currency = "PRE002";//港币
                break;
            case "EUR":
                currency = "PRE003";//欧元
                break;
            case "JPY":
                currency = "PRE004";//日元
                break;
            case "GBP":
                currency = "PRE006";//英镑
                break;
            case "USD":
                currency = "PRE007";//美元
                break;
            case "ISK":
                currency = "PRE008";//克朗
                break;
            default:
                break;
        }

        String rating = StringUtils.replaceNullString(account.getRating());
        String freezeTime = StringUtils.replaceNullString(account.getFreezeTime());
        String acctName = StringUtils.replaceNullString(account.getAcctName());
        String acctCode = StringUtils.replaceNullString(account.getAcctCode());
        String simName = StringUtils.replaceNullString(account.getSimName());
        String fixedPhone = StringUtils.replaceNullString(account.getFixedPhone());
        String address = StringUtils.replaceNullString(account.getAddress());
        String websiteAddr = StringUtils.replaceNullString(account.getWebsiteAddr());
        String billTitle = StringUtils.replaceNullString(account.getBillTitle());
        String accountBankName = StringUtils.replaceNullString(account.getAccountBankName());
        String taxpayerNumber = StringUtils.replaceNullString(account.getTaxpayerNumber());
        String billPhone = StringUtils.replaceNullString(account.getBillPhone());
        String billAddr = StringUtils.replaceNullString(account.getBillAddr());
        String regTaxNum = StringUtils.replaceNullString(account.getRegTaxNum());
        String fax = StringUtils.replaceNullString(account.getFax());

        fCreateOrgId.put("FNumber","00");//创建组织
        fUseOrgId.put("FNumber","00");//使用组织
        fCOUNTRY.put("FNumber",country);//国家
        fCustTypeId.put("FNumber",acctCategor);//客户类别
        fCurrencyId.put("FNumber",currency);//币别
        fTaxType.put( "FNumber","SFL02_SYS");//税分类：默认
        fTaxRate.put("FNumber",rating);//默认税率
        ftBdCustomerext.put("FEnableSL",false); //启用商联在线
        //冻结状态
        if ("Freezed".equals(account.getAcctStatus())) {
            ftBdCustomerext.put("FFreezeDate",freezeTime);//冻结日期
            ftBdCustomerext.put("FFreezeStatus",true);  //冻结状态
        }

        model.put("FCUSTID",0);  //客户实体主键：默认0
        model.put("FCreateOrgId",fCreateOrgId);//创建组织
        model.put("FUseOrgId",fUseOrgId);//使用组织
        model.put("FName",acctName);//客户名称

        model.put("FNumber",acctCode);//客户编码
        model.put("FShortName",simName); //客户简称
        model.put("FTEL",fixedPhone); //联系电话
        model.put("FFAX",fax);//传真
        model.put("FADDRESS",address);//详细地址
        model.put("FWEBSITE",websiteAddr);//门户网站

        model.put( "FCOUNTRY",fCOUNTRY);//国家
        model.put("FINVOICETITLE",billTitle); //发票抬头

        model.put("FINVOICEBANKNAME",accountBankName); //开户银行
        model.put("FINVOICEBANKACCOUNT",taxpayerNumber); //银行账号
        model.put("FINVOICETEL",billPhone); //开票联系电话
        model.put("FINVOICEADDRESS",billAddr); //开票通讯地址
        model.put("FTAXREGISTERCODE",regTaxNum); //纳税登记号

        model.put("FIsGroup",false);//集团客户
        model.put( "FIsDefPayer",false);//默认付款方
        model.put("FCustTypeId",fCustTypeId);//客户类别
        model.put("FTRADINGCURRID",fCurrencyId); //币别
        model.put("FInvoiceType","1"); //发票类型
        model.put( "FTaxType",fTaxType);//税分类
        model.put("FPriority",1);//客户优先级
        model.put("FTaxRate",fTaxRate);//默认税率
        model.put("FISCREDITCHECK",false);//启用信用管理
        model.put("FIsTrade",true);//是否交易客户
        model.put("FT_BD_CUSTOMEREXT",ftBdCustomerext);//商务信息

        JSONArray needUpDateFields = new JSONArray();
        JSONArray needReturnFields = new JSONArray();

        JSONObject jsonObject = new JSONObject(true);
        jsonObject.put("Creator","");
        jsonObject.put("NeedUpDateFields",needUpDateFields);
        jsonObject.put("NeedReturnFields",needReturnFields);
        jsonObject.put("IsDeleteEntry","true");
        jsonObject.put("SubSystemId","");
        jsonObject.put("IsVerifyBaseDataField","false");
        jsonObject.put("IsEntryBatchFill","true");
        jsonObject.put("ValidateFlag","true");
        jsonObject.put("NumberSearch","true");
        jsonObject.put("InterationFlags","");
        jsonObject.put("IsAutoSubmitAndAudit","true");   //传输至ERP是审核通过状态,新增是true，更新是false
        jsonObject.put("Model",model);

        JSONArray requestArray = new JSONArray();
        requestArray.add("BD_Customer");
        requestArray.add(jsonObject);

        JSONObject requestObject = new JSONObject();
        requestObject.put("parameters",requestArray);
        //至此，请求body成形，将他转化为字符串格式
        String data = JsonUtil.toString(requestObject);
        logger.info(data);

        //返回写入此连接的输出流。
        PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
        //发送参数 把刚才的请求body写入http输出流
        printWriter.write(data);
        printWriter.flush();
        String line;
        String result = "";
        //返回这个打开的链接读取的输入流 获取返回内容  逐行读取返回结果
        BufferedReader in = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
        while ((line = in.readLine()) != null) {
            result += line;
        }
        logger.info(result);
        //response信息处理
        return analyzeResponse(result);
    }

    /**
     * 客户变更审批通过，同步修改内容至erp
     * @param entity
     * @throws Exception
     */
    @Override
    public void syncAccountChange(Account entity) throws Exception {
        //遍历插入修改的字段，修改CUSTID为account的erpID
        //根据传进来的客户ID，查询客户信息
        Account account = accountService.queryById(entity);
        if (account == null) {
            //没找到对应合同头：未找到对应的合同头信息，请检查
            logger.info("客户变更信息同步接口 -> URL:/link/accnt -> 异常信息：{}  -> 客户ID：{}", "未找到对应的客户头信息，客户信息同步失败",entity.getId());
        }
        //调用ERP客户写入接口
        EsbInfo esbInfo = syncAcctChangeToERP(account);
        logger.info("客户变更信息同步接口 -> URL:/link/accnt -> 返回信息：{}", esbInfo);
    }


    /**
     * 客户信息变更
     * 调用ERP客户写入接口，更新erp数据
     * @return
     * @throws Exception
     */
    public EsbInfo syncAcctChangeToERP(Account account) throws Exception {
        //获取公共参数 查询应收单开票信息
        String requestUrl  = PropertyUtil.getCommonProperty("syncAccountInfo");
        // 转换成特定格式字符串 打开url的http请求
        URL url = new URL(requestUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
        // 提交模式
        httpURLConnection.setRequestMethod("POST");  //接口文档上标注的传输方式
        httpURLConnection.setDoOutput(true);// URL连接可用于输入和/或输出。如果您打算将URL连接用于输出，请将DoOutput标志设置为true，否则将其设置为false
        httpURLConnection.setDoInput(true);
        httpURLConnection.setRequestProperty("Authorization",PropertyUtil.getCommonProperty("returnUrlAuth")); //设置常规请求属性 这里改为参数配置的key
        httpURLConnection.setRequestProperty("Content-type", "application/json");

        //构造参数 由内到外，从最内层零件对象开始
        JSONObject model = new JSONObject(true);    //存放头信息,有序
        JSONObject fCreateOrgId = new JSONObject();  //创建组织
        JSONObject fUseOrgId = new JSONObject();  //使用组织
        JSONObject fCOUNTRY = new JSONObject();//国家
        JSONObject fCustTypeId = new JSONObject();//客户类别
        JSONObject fCurrencyId = new JSONObject();  //币别
        JSONObject fTaxType = new JSONObject();//税分类
        JSONObject fTaxRate = new JSONObject();//默认税率
        JSONObject ftBdCustomerext = new JSONObject();//商务信息

        String country = StringUtils.replaceNullString(account.getCountry());
        String acctCategor = StringUtils.replaceNullString(account.getAcctCategory());
        //币别转换
        String currency = StringUtils.replaceNullString(account.getCurrency());
        switch (currency) {
            case "CNY":
                currency = "PRE001";  //人民币
                break;
            case "HKD":
                currency = "PRE002";//港币
                break;
            case "EUR":
                currency = "PRE003";//欧元
                break;
            case "JPY":
                currency = "PRE004";//日元
                break;
            case "GBP":
                currency = "PRE006";//英镑
                break;
            case "USD":
                currency = "PRE007";//美元
                break;
            case "ISK":
                currency = "PRE008";//克朗
                break;
            default:
                break;
        }

        String rating = StringUtils.replaceNullString(account.getRating());
        String freezeTime = StringUtils.replaceNullString(account.getFreezeTime());
        String acctName = StringUtils.replaceNullString(account.getAcctName());
        String acctCode = StringUtils.replaceNullString(account.getAcctCode());
        String simName = StringUtils.replaceNullString(account.getSimName());
        String fixedPhone = StringUtils.replaceNullString(account.getFixedPhone());
        String address = StringUtils.replaceNullString(account.getAddress());
        String websiteAddr = StringUtils.replaceNullString(account.getWebsiteAddr());
        String billTitle = StringUtils.replaceNullString(account.getBillTitle());
        String accountBankName = StringUtils.replaceNullString(account.getAccountBankName());
        String taxpayerNumber = StringUtils.replaceNullString(account.getTaxpayerNumber());
        String billPhone = StringUtils.replaceNullString(account.getBillPhone());
        String billAddr = StringUtils.replaceNullString(account.getBillAddr());
        String regTaxNum = StringUtils.replaceNullString(account.getRegTaxNum());
        String fax = StringUtils.replaceNullString(account.getFax());
        String fCUSTID = StringUtils.replaceNullString(account.getErpId());

        fCreateOrgId.put("FNumber","00");//创建组织
        fUseOrgId.put("FNumber","00");//使用组织
        fCOUNTRY.put("FNumber",country);//国家
        fCustTypeId.put("FNumber",acctCategor);//客户类别
        fCurrencyId.put("FNumber",currency);//币别
        fTaxType.put( "FNumber","SFL02_SYS");//税分类：默认
        fTaxRate.put("FNumber",rating);//默认税率
        ftBdCustomerext.put("FEnableSL",false); //启用商联在线
        //冻结状态
        if ("Freezed".equals(account.getAcctStatus())) {
            ftBdCustomerext.put("FFreezeDate",freezeTime);//冻结日期
            ftBdCustomerext.put("FFreezeStatus",true);  //冻结状态
        }

        model.put("FCUSTID",fCUSTID);  //客户实体主键：之前调用接口新增数据返回的erpID
        model.put("FCreateOrgId",fCreateOrgId);//创建组织
        model.put("FUseOrgId",fUseOrgId);//使用组织
        model.put("FName",acctName);//客户名称

        model.put("FNumber",acctCode);//客户编码
        model.put("FShortName",simName); //客户简称
        model.put("FTEL",fixedPhone); //联系电话
        model.put("FFAX",fax);//传真
        model.put("FADDRESS",address);//详细地址
        model.put("FWEBSITE",websiteAddr);//门户网站

        model.put("FCOUNTRY",fCOUNTRY);//国家
        model.put("FINVOICETITLE",billTitle); //发票抬头

        model.put("FINVOICEBANKNAME",accountBankName); //开户银行
        model.put("FINVOICEBANKACCOUNT",taxpayerNumber); //银行账号
        model.put("FINVOICETEL",billPhone); //开票联系电话
        model.put("FINVOICEADDRESS",billAddr); //开票通讯地址
        model.put("FTAXREGISTERCODE",regTaxNum); //纳税登记号

        model.put("FIsGroup",false);//集团客户
        model.put("FIsDefPayer",false);//默认付款方
        model.put("FCustTypeId",fCustTypeId);//客户类别
        model.put("FTRADINGCURRID",fCurrencyId); //币别
        model.put("FInvoiceType","1"); //发票类型
        model.put("FTaxType",fTaxType);//税分类
        model.put("FPriority",1);//客户优先级
        model.put("FTaxRate",fTaxRate);//默认税率
        model.put("FISCREDITCHECK",false);//启用信用管理
        model.put("FIsTrade",true);//是否交易客户
        model.put("FT_BD_CUSTOMEREXT",ftBdCustomerext);//商务信息

        JSONArray needUpDateFields = new JSONArray();   //填写需要更新的字段
        JSONArray needReturnFields = new JSONArray();

        //判断客户变更的所有字段（客户名称，客户编码，父客户名称，纳税登记号，开户银行，银行账号，开票联系地址）是否为空，为空的字段不更新，不为空的字段更新
        if (!acctName.equals("") ) {
            needReturnFields.add("FName");
        }
        if (!acctCode.equals("") ) {
            needReturnFields.add("FNumber");
        }
        if (!regTaxNum.equals("")) {
            needReturnFields.add("FTAXREGISTERCODE");
        }
        if (!accountBankName.equals("")) {
            needReturnFields.add("FINVOICEBANKNAME"); //开户银行
        }
        if (!taxpayerNumber.equals("")) {
            needReturnFields.add("FINVOICEBANKACCOUNT");//银行账号
        }
        if (!billAddr.equals("")) {
            needReturnFields.add("FINVOICEADDRESS");//开票通讯地址
        }


        JSONObject jsonObject = new JSONObject(true);
        jsonObject.put("Creator","");
        jsonObject.put("NeedUpDateFields",needUpDateFields);
        jsonObject.put("NeedReturnFields",needReturnFields);
        jsonObject.put("IsDeleteEntry","true");
        jsonObject.put("SubSystemId","");
        jsonObject.put("IsVerifyBaseDataField","false");
        jsonObject.put("IsEntryBatchFill","true");
        jsonObject.put("ValidateFlag","true");
        jsonObject.put("NumberSearch","true");
        jsonObject.put("InterationFlags","");
        jsonObject.put("IsAutoSubmitAndAudit","false");   //传输至ERP是审核通过状态,新增是true，更新是false
        jsonObject.put("Model",model);

        JSONArray requestArray = new JSONArray();

        requestArray.add("BD_Customer");
        requestArray.add(jsonObject);

        JSONObject requestObject = new JSONObject();
        requestObject.put("parameters",requestArray);
        //至此，请求body成形，将他转化为字符串格式
        String data = JsonUtil.toString(requestObject);
        logger.info(data);

        //返回写入此连接的输出流。
        PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
        //发送参数 把刚才的请求body写入http输出流
        printWriter.write(data);
        printWriter.flush();
        String line;
        String result = "";
        //返回这个打开的链接读取的输入流 获取返回内容  逐行读取返回结果
        BufferedReader in = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
        while ((line = in.readLine()) != null) {
            result += line;
        }
        logger.info(result);
        //response信息处理
        return analyzeResponse(result);
    }

    /**
     * 处理接口返回信息
     * 客户同步接口，价格合同接口
     * @param response
     * @return
     */
    public EsbInfo analyzeResponse(String response) {
        EsbInfo esbInfo = new EsbInfo();
        esbInfo.setResponseTime(ApiUtil.getCurrentDetailTime());  //获取当前时间的详细时间
        //拿到回传信息，将字符串解析为对象
        JSONObject responseInfo = JSONObject.parseObject(response);
        JSONObject result = JSONObject.parseObject(responseInfo.get("Result").toString());
        JSONObject responseStatus = JSONObject.parseObject(result.get("ResponseStatus").toString());
        boolean isSuccess = (boolean) responseStatus.get("IsSuccess");
        //根据ResponseStatus判断是否同步成功
        if (isSuccess) {
            //同步成功，获取ID + 存入本条客户信息erpid字段
            String ERPID = result.get("Id").toString();  //ERP回传ID
            String acctCode = result.get("Number").toString(); //客户编码、ERP销售价目编号
            //更新数据库记录成功
            esbInfo.setReturnStatus(EsbInfo.A0002)
                    .setAttr1(ERPID)
                    .setAttr2(acctCode);
        } else {
            //同步失败，获取ID和原因
            JSONArray errorsArray = JSONArray.parseArray(responseStatus.getString("Errors"));
            JSONObject errorDetail = errorsArray.getJSONObject(0);  //注意这里只拿了Errors数组的第一条错误
            String errorCode = responseStatus.get("ErrorCode").toString();//接口返回状态码，与returnMsg成对出现
            String errorMessage = errorDetail.get("Message").toString();  //错误信息
            String fieldName =  errorDetail.get("FieldName").toString();  //错误字段名称
            esbInfo.setReturnStatus(EsbInfo.E0999)
                    .setReturnCode(errorCode)
                    .setReturnMsg(errorMessage)
                    .setAttr2(fieldName);
        }
        return esbInfo;
    }

    /**
     * 定时同步到本系统
     * 查询ERP物料编码信息并更新
     * @throws Exception
     */
    @Override
    public void upsertMaterialFromERP() throws Exception {
        //查询接口数据
        JSONArray resultLists = queryMaterial();
        //处理返回数据
//        JSONArray resultArray = (JSONArray) JSON.parse(resultStr);
        int resultListsSize = resultLists.size();
        int l;   //外层 循环变量
        int i;  //内层 循环变量
        for (l = 0 ; l < resultListsSize; l++) {
            //处理数据 [[],[],[]...]
            JSONArray resultArray = JSONArray.parseArray((String) resultLists.get(l));
            int size = resultArray.size();
            MaterialCode materialCode = new MaterialCode();
            for (i = 0; i < size; i++) {
                JSONArray fMaterial = resultArray.getJSONArray(i);
                materialCode.setMaterialCode(fMaterial.get(0).toString());//物料编码
                materialCode.setPartCode(fMaterial.get(1).toString());//零件号
                materialCode.setPartName(fMaterial.get(2).toString());//零件名称
                materialCode.setfUseOrgId(fMaterial.get(3).toString());//使用组织
                materialCode.setfBaseUnit(fMaterial.get(4).toString());//计价单位
                materialCode.setErpId(fMaterial.get(5).toString());//ERPID
                materialCode.setfBaseUnitCode(fMaterial.get(6).toString());//计价单位编码
                logger.info("物料编码数据接口 -> JobHandler:materialJobHandler -> 接收数据：{}", fMaterial.toString());
                //数据校验
                materialCheck(materialCode);
                MaterialCode exactOne = materialCodeService.queryOneByErpId(materialCode);
                if (exactOne != null) {
                    //走更新逻辑
                    try {
                        materialCode.setId(exactOne.getId());
                        materialCodeService.update(materialCode);
                    } catch (Exception e) {
                        logger.error("物料编码数据接口Service异常 -> 异常数据: {} -> 异常信息：{}", materialCode,e.getMessage());
                    }
                } else {
                    //走新建逻辑
                    try {
                        materialCode.setId(keyGenerateService.keyGenerate());
                        materialCodeService.insert(materialCode);
                    } catch (Exception e) {
                        logger.error("物料编码数据接口Service异常 -> 异常数据: {} -> 异常信息：{}", materialCode ,e.getMessage());
                    }
                }
            }
        }
    }

    /**
     * 查询ERP物料编码
     * @return
     * @throws Exception
     */
    public JSONArray queryMaterial() throws Exception {
        //获取公共参数 查询应收单开票信息
        String requestUrl  = PropertyUtil.getCommonProperty("materialCodeUrl");
        // 转换成特定格式字符串 打开url的http请求
        URL url = new URL(requestUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
        // 提交模式
        httpURLConnection.setRequestMethod("POST");  //接口文档上标注的传输方式
        httpURLConnection.setDoOutput(true);// URL连接可用于输入和/或输出。如果您打算将URL连接用于输出，请将DoOutput标志设置为true，否则将其设置为false
        httpURLConnection.setDoInput(true);
        httpURLConnection.setRequestProperty("Authorization",PropertyUtil.getCommonProperty("returnUrlAuth")); //设置常规请求属性 这里改为参数配置的key
        httpURLConnection.setRequestProperty("Content-type", "application/json");

        //构造参数  就是构造请求body-->{body}
        JSONObject jsonObject = new JSONObject(true);
        jsonObject.put("FormId","BD_MATERIAL");
        jsonObject.put("TopRowCount",0);
        jsonObject.put("Limit",1000);
        jsonObject.put("StartRow",0);
            //查询使用组织是集团数据中心，物料编码05开头，最后更新时间在上周内的数据
        jsonObject.put("FilterString","FUSEORGID=100004 and fnumber like '05.%' "
                + "and datediff(week,FApproveDate,getdate()) = 1 and FDOCUMENTSTATUS = 'C'");
        jsonObject.put("OrderString","FApproveDate asc");
        jsonObject.put("FieldKeys","FNUMBER,FSpecification,FNAME,FUSEORGID,FBaseUnitId.FNAME,FMATERIALID,FBaseUnitId.FNumber");
        //new一个json数组 刚才构造的请求{body}对象外加一层 -->[{body}]
        JSONArray jsonArray = new JSONArray();
        jsonArray.add(jsonObject);
        //new一个json对象 把刚才的[{body}]外面再加一层 --> {"parameters":[{body}]}
        JSONObject paramJson = new JSONObject();
        paramJson.put("parameters",jsonArray);
        //至此，请求body成形，将他转化为字符串格式
        String data = JsonUtil.toString(paramJson);
        logger.info(data);

        //返回写入此连接的输出流。
        PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
        //发送参数 把刚才的请求body写入http输出流
        printWriter.write(data);
        printWriter.flush();
        String line;
        JSONArray resultList = new JSONArray();
        for (int i = 0 ; i < 5 ;i++) {
            String result = "";
            //返回这个打开的链接读取的输入流 获取返回内容  逐行读取返回结果
            BufferedReader in = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
            while ((line = in.readLine()) != null) {
                result += line;
            }
            logger.info(result);
            if (result == null || result == "") {
                //为空说明上周更新的数据全部查完 跳出本循环 返回数组
                break;
            } else {
                //不为空，则说明查询到数据，addlist
                resultList.add(result);
                //动态构造StartRow
                LinkRedisClient jedis = RedisUtil.getJedis();
                int startRow = 0 ;
                try {
                    String redisKey = "interfaceStartRow" + "/" + DateUtil.dateToStr(new Date(), "yyyyMMdd");

                    if (jedis.hexists(redisKey,"materialInfo")) {
                        //有今天的key,说明不是第一次查询-->在原有的值得基础上+1000
                        int old = Integer.parseInt(jedis.hget(redisKey, "materialInfo"));
                        jedis.hincrBy(redisKey,"materialInfo",1000);
                        startRow = Integer.parseInt(jedis.hget(redisKey, "materialInfo"));
                    } else {
                        //没有今天的key,说明第2次查询[startRow赋值1000]-->创建以上述RedisKey为key,值为1000的数据
                        jedis.hset(redisKey,"materialInfo", String.valueOf(1000));
                        startRow = Integer.parseInt(jedis.hget(redisKey, "materialInfo"));
                    }
                } catch (Exception e) {
                    LCLogger.withException(e);
                } finally {
                    RedisUtil.returnResource(jedis);
                }
                jsonObject.put("StartRow",startRow);
            }
        }
        return resultList;
    }

    /**
     * 物料编码信息校验
     * @param materialCode
     */
    private void materialCheck(MaterialCode materialCode) {
        if (Objects.isNull(materialCode)) {
            logger.error("物料编码数据接口Service异常  -> 异常信息：{}", "保存数据对象为空");
        }
        //判断erpId  erp开票信息行是否为空
        if (StringUtils.isBlank(materialCode.getErpId())) {
            logger.error("物料编码数据接口Service异常  -> 异常信息：{}", "字段非空校验失败");
        }
    }
}
